package com.gitee.ly;

import lombok.extern.slf4j.Slf4j;

import java.lang.management.*;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
public class JvmInfoTimePrintManage {
    //可随时动态控制打印开关，默认关闭
    public static volatile boolean controlPrint = false;
    private static final MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
    private static final ScheduledThreadPoolExecutor timePrintScheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1, new DemonThreadFactory());

    static {
        timePrintScheduledThreadPoolExecutor.scheduleWithFixedDelay(JvmInfoTimePrintManage::print, 30, 60, TimeUnit.SECONDS);
    }

    public static void print() {
        try {
            if (controlPrint) {
                //cpu
                com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
                String cpuUseInfo = String.format("CPU使用率： JAVA进程CPU使用率(%.2f%%) 机器CPU使用率(%.2f%%)",
                        os.getProcessCpuLoad() * 100,
                        os.getSystemCpuLoad() * 100
                );
                log.info(cpuUseInfo);
                //机器内存
                String deviceUseInfo = String.format("机器内存情况： 物理内存总量：(%sMb) 物理内存剩余：(%sMb)",
                        os.getTotalPhysicalMemorySize() / 1024 / 1024,
                        os.getFreePhysicalMemorySize() / 1024 / 1024
                );
                log.info(deviceUseInfo);
                //内存
                MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
                String heapUseInfo = String.format("堆内内存使用情况： 初始化内存(%sMb) 当前总内存(%sMb) 当前已用内存(%sMb) 当前剩余内存(%sMb) 最大内存(%sMb)",
                        heapMemoryUsage.getInit() / 1024 / 1024,
                        heapMemoryUsage.getCommitted() / 1024 / 1024,
                        heapMemoryUsage.getUsed() / 1024 / 1024,
                        (heapMemoryUsage.getCommitted() - heapMemoryUsage.getUsed()) / 1024 / 1024,
                        heapMemoryUsage.getMax() / 1024 / 1024
                );
                log.info(heapUseInfo);
                MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
                String noHeapUseInfo = String.format("堆外内存使用情况： 初始化内存(%sMb) 当前总内存(%sMb) 当前已用内存(%sMb) 当前剩余内存(%sMb) 最大内存(%sMb)",
                        nonHeapMemoryUsage.getInit() / 1024 / 1024,
                        nonHeapMemoryUsage.getCommitted() / 1024 / 1024,
                        nonHeapMemoryUsage.getUsed() / 1024 / 1024,
                        (nonHeapMemoryUsage.getCommitted() - nonHeapMemoryUsage.getUsed()) / 1024 / 1024,
                        nonHeapMemoryUsage.getMax() / 1024 / 1024
                );
                log.info(noHeapUseInfo);

                //内存池
                List<MemoryPoolMXBean> memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans();
                for (MemoryPoolMXBean memoryPoolMXBean : memoryPoolMXBeans) {
                    MemoryUsage usage = memoryPoolMXBean.getUsage();
                    MemoryUsage collectionUsage = memoryPoolMXBean.getCollectionUsage();
                    String memoryPoolUseInfo = String.format("内存池(%s)(%s)内存使用情况： 初始化内存(%sMb) 当前总内存(%sMb) 当前已用内存(%sMb) 当前剩余内存(%sMb) 最大内存(%sMb)",
                            memoryPoolMXBean.getType(),
                            memoryPoolMXBean.getName(),
                            usage.getInit() / 1024 / 1024,
                            usage.getCommitted() / 1024 / 1024,
                            usage.getUsed() / 1024 / 1024,
                            (usage.getCommitted() - usage.getUsed()) / 1024 / 1024,
                            usage.getMax() / 1024 / 1024
                    );
                    if (collectionUsage != null) {
                        String collectionUsageStr = String.format(" 该池最近一次回收后内存情况：[初始化内存(%sMb) 当前总内存(%sMb) 当前已用内存(%sMb) 当前剩余内存(%sMb) 最大内存(%sMb)]",
                                collectionUsage.getInit() / 1024 / 1024,
                                collectionUsage.getCommitted() / 1024 / 1024,
                                collectionUsage.getUsed() / 1024 / 1024,
                                (collectionUsage.getCommitted() - collectionUsage.getUsed()) / 1024 / 1024,
                                collectionUsage.getMax() / 1024 / 1024
                        );
                        memoryPoolUseInfo = memoryPoolUseInfo + collectionUsageStr;
                    }
                    log.info(memoryPoolUseInfo);
                }
                // 获取所有垃圾回收器的信息
                for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
                    String gcBeanInfo = String.format("垃圾回收器(%s)： 已回收次数(%s) 已回收次数总耗时(%s秒)",
                            gcBean.getName(),
                            gcBean.getCollectionCount(),
                            gcBean.getCollectionTime() / 1000
                    );
                    log.info(gcBeanInfo);
                }
            }
        } catch (Throwable ex) {
            log.error(ex.getMessage(), ex);
        }
    }
}